import {
  OnGatewayConnection,
  OnGatewayDisconnect,
  OnGatewayInit,
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  MessageBody,
  ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { AuthService } from './auth.service';
import {
  EVENT_OFFLINE,
  EVENT_ONLINE,
  SEND_ONLINE_MACHINE_CODE_LIST,
  GET_MACHINE_WS_DATA,
  SEND_MACHINE_CODE_OBJ_DATA,
  LOAD_ORDER_LIST,
} from './ws.event';

/**
 * Admin WebSokcet网关，不含权限校验，Socket端只做通知相关操作
 */
@WebSocketGateway()
export class AdminWSGateway implements OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit {
  @WebSocketServer()
  private wss: Server;

  get socketServer(): Server {
    return this.wss;
  }

  constructor(private authService: AuthService) {}

  /**
   * OnGatewayInit
   * @param server Server
   */
  afterInit() {
    // TODO
  }

  sendSocketList = [];

  machineCodeObj = {};

  onlineMachineCodeList = [];

  async sendOnlineMachineCodeList() {
    const socketList: any = await this.wss.fetchSockets();

    this.onlineMachineCodeList = [];

    this.sendSocketList = [];

    for (const client of socketList) {
      const { machineCode: iMachineCode, isElectron: iIsElectron } = client.handshake?.query || {};

      if (Number(iIsElectron) && iMachineCode && this.machineCodeObj[iMachineCode]) {
        this.onlineMachineCodeList.push(iMachineCode);

        client.emit(GET_MACHINE_WS_DATA);
      }

      if (!Number(iIsElectron) && !iMachineCode) {
        this.sendSocketList.push(client);
      }
    }

    for (const client of this.sendSocketList) {
      client.emit(SEND_ONLINE_MACHINE_CODE_LIST, this.onlineMachineCodeList);

      client.emit(SEND_MACHINE_CODE_OBJ_DATA, this.machineCodeObj);
    }
  }

  /**
   * OnGatewayConnection
   */
  async handleConnection(client: Socket): Promise<void> {
    const { token = null, machineCode } = client.handshake?.query || {};

    try {
      this.authService.checkAdminAuthToken(token);

      this.sendOnlineMachineCodeList();
    } catch (e) {
      // no auth
      client.disconnect();
      return;
    }

    console.log(machineCode + 'online');

    // broadcast online
    client.broadcast.emit(EVENT_ONLINE, machineCode);

    // client.on('productionCenterData', (data: any) => {
    //   console.log('Received message from client:', data);
    //   // 在这里处理接收到的消息
    // });
  }

  /**
   * OnGatewayDisconnect
   */
  async handleDisconnect(client: Socket): Promise<void> {
    // TODO
    const { machineCode } = client.handshake?.query || {};

    client.broadcast.emit(EVENT_OFFLINE, machineCode);

    this.sendOnlineMachineCodeList();

    console.log(machineCode + 'offline');
  }

  @SubscribeMessage('productionCenterData')
  handleProductionCenterDataMessage(
    @MessageBody() data: any,
    @ConnectedSocket() _client: Socket
  ): void {
    // console.log('Received message:', data);

    if (data && typeof data === 'object') {
      const { machine } = data;

      if (machine) {
        const { machineCode } = machine;

        this.machineCodeObj[machineCode] = data;

        if (!this.onlineMachineCodeList.includes(machineCode)) {
          this.sendOnlineMachineCodeList();
        }

        for (const client of this.sendSocketList) {
          client.emit(SEND_MACHINE_CODE_OBJ_DATA, this.machineCodeObj);
        }
      }
    }

    // console.log(client);

    // console.log(client.id);
    // 在这里处理接收到的消息
  }

  @SubscribeMessage('sendMachineCodeLoadOrder')
  async handleSendMachineCodeLoadOrderMessage(
    @MessageBody() data: any,
    @ConnectedSocket() _client: Socket
  ) {
    // console.log('Received message:', data);

    if (data && typeof data === 'object') {
      const { machineCode } = data;

      if (machineCode) {
        const socketList: any = await this.wss.fetchSockets();

        for (const client of socketList) {
          const { machineCode: iMachineCode, isElectron: iIsElectron } =
            client.handshake?.query || {};

          if (Number(iIsElectron) && iMachineCode === machineCode) {
            client.emit(LOAD_ORDER_LIST);
          }
        }
      }
    }

    // console.log(client);

    // console.log(client.id);
    // 在这里处理接收到的消息
  }
}
